<template>
  <van-overlay :show="show" z-index="2" @click="show = false">
    <div class="trtcCalling-container" @click.stop>
      <div class="trtcCalling-answer-title" v-show="statusName === '接听' && videoChangeFlag">
        <p class="trtcCalling-answer-title-name">{{ inviterName }}</p>
      </div>
      <div class="trtcCalling-call-title" v-show="statusName !== '接听'">
        <p class="trtcCalling-call-title-name">{{ inviterName }}</p>
        <p class="trtcCalling-call-title-text">与您进行视频通话</p>
      </div>
      <div class="trtcCalling-video">
        <div class="trtcCalling-video-big" id="video-big"></div>
        <div class="trtcCalling-video-small" id="video-small-warp" v-drag>
          <div class="trtcCalling-video-small-video" id="video-small" @click="handleVideoClick"></div>
          <p class="trtcCalling-video-small-text" v-show="!videoChangeFlag">{{ inviterName }}</p>
        </div>
      </div>
      <div class="trtcCalling-operate">
        <p class="trtcCalling-operate-duration">{{ durationFormat }}</p>
        <van-row v-show="statusName === '接听'">
          <van-col :span="8" align="center">
            <img
              :src="require(`@/assets/images/trtc/icon_audio_${isAudioAvailable ? 'off' : 'on'}@2x.png`)"
              class="trtcCalling-operate-img"
              alt=""
              @click="handleChangeAudioAvailable"
            />
            <p class="trtcCalling-operate-text">静音</p>
          </van-col>
          <van-col :span="8" align="center">
            <img
              src="@/assets/images/trtc/icon_cancel@2x.png"
              class="trtcCalling-operate-img"
              alt=""
              @click="handleHangup"
            />
            <p class="trtcCalling-operate-text">取消</p>
          </van-col>
          <van-col :span="8" align="center">
            <img
              src="@/assets/images/trtc/icon_camera_change.png"
              class="trtcCalling-operate-img"
              alt=""
              @click="handleChangeCamera"
            />
            <p class="trtcCalling-operate-text">转换摄像头</p>
          </van-col>
        </van-row>
        <van-row v-show="statusName !== '接听'">
          <van-col span="12" align="center">
            <img
              src="@/assets/images/trtc/icon_answer@2x.png"
              class="trtcCalling-operate-img"
              alt=""
              @click="handleAccept"
            />
            <p class="trtcCalling-operate-text">接听</p>
          </van-col>
          <van-col span="12" align="center">
            <img
              src="@/assets/images/trtc/icon_cancel@2x.png"
              class="trtcCalling-operate-img"
              alt=""
              @click="handleRejectCall"
            />
            <p class="trtcCalling-operate-text">取消</p>
          </van-col>
        </van-row>
      </div>
    </div>
  </van-overlay>
</template>
<script>
import { mapState } from 'vuex'
import { createTrtcCalling, getUserSig } from '@/trtc'
import { formatTimes } from '@/libs/tool'
let timeout
export default {
  name: 'trtccall',
  data() {
    return {
      show: false,
      // 视频通话
      trtcCalling: null,
      // 邀请方UserId
      inviterUserId: '',
      // 邀请方姓名
      inviterName: '',
      // 邀请信息
      inviteData: {},
      // 邀请ID
      inviteID: '',
      // 状态
      statusName: '',
      // 是否静音
      isAudioAvailable: true,
      // 视频切换
      videoChangeFlag: true,
      // 摄像头切换
      cameras: [],
      camerasIndex: 0,
      // 计时
      timer: null,
      duration: 0,
      durationFormat: '',
      callPerson: {}
    }
  },
  computed: {
    ...mapState({
      user: state => state.userInfo
    })
  },
  watch: {
    'user.token'() {
      Object.keys(localStorage).forEach(function (key) {
        if (/^TIM_|^loglevel/.test(key)) {
          localStorage.removeItem(key)
        }
      })
      if (this.user.token) {
        // 初始化视频通话
        this.initTrtcCalling()
      } else {
        // 视频通话 - 退出登录
        this.removeListener()
        this.trtcCalling.logout()
      }
    }
  },
  created() {
    if (this.user.token) {
      // 初始化视频通话
      this.initTrtcCalling()
      // window.addEventListener('beforeunload', e => this.beforeunloadHandler(e))
    }
    window.TRTC.getCameras().then(devices => {
      this.cameras = devices
    })
  },
  mounted() {},
  methods: {
    // 初始化视频通话
    initTrtcCalling() {
      this.trtcCalling = createTrtcCalling()
      this.trtcCalling.logout()
      this.trtcCalling.login({
        userID: this.user.phone,
        userSig: getUserSig(this.user.phone)
      })
      this.initListener()
    },
    // 浏览器关闭处理
    beforeunloadHandler(e) {
      e = e || window.event
      if (e) {
        e.returnValue = '关闭提示'
        Object.keys(localStorage).forEach(function (key) {
          if (/^TIM_|^loglevel/.test(key)) {
            localStorage.removeItem(key)
          }
        })
        this.removeListener()
        this.trtcCalling.logout()
      }
    },
    // 本地用户开启/关闭了麦克风
    handleChangeAudioAvailable() {
      this.trtcCalling.setMicMute(this.isAudioAvailable)
      this.isAudioAvailable = !this.isAudioAvailable
    },
    // 摄像头切换
    handleChangeCamera() {
      this.camerasIndex = this.camerasIndex === 0 ? (this.cameras[this.camerasIndex].deviceId ? 1 : 0) : 0
      this.trtcCalling.switchDevice('video', this.cameras[this.camerasIndex].deviceId)
    },
    initListener() {
      // 收到了邀请通知
      this.trtcCalling.on(window.TRTCCalling.EVENT.INVITED, this.handleNewInvitationReceived)
      // 本次通话被取消了
      this.trtcCalling.on(window.TRTCCalling.EVENT.CALLING_CANCEL, this.handleInviterCancel)
      // 本次通话超时未应答
      this.trtcCalling.on(window.TRTCCalling.EVENT.CALLING_TIMEOUT, this.handleCallTimeout)
      // 用户进房
      this.trtcCalling.on(window.TRTCCalling.EVENT.USER_ENTER, this.handleUserEnter)
      // 用户退出房间
      this.trtcCalling.on(window.TRTCCalling.EVENT.USER_LEAVE, this.handleUserLeave)
      // 重复登录，被踢出房间
      this.trtcCalling.on(window.TRTCCalling.EVENT.KICKED_OUT, this.handleKickedOut)
      // 远端用户开启/关闭了摄像头
      this.trtcCalling.on(window.TRTCCalling.EVENT.USER_VIDEO_AVAILABLE, this.handleUserVideoChange)
      // 远端用户开启/关闭了麦克风
      this.trtcCalling.on(window.TRTCCalling.EVENT.USER_AUDIO_AVAILABLE, this.handleUserAudioChange)
      // 本次通话结束
      this.trtcCalling.on(window.TRTCCalling.EVENT.CALLING_END, this.handleCallEnd)
      // 错误回调
      this.trtcCalling.on(window.TRTCCalling.EVENT.ERROR, this.handleError)
    },
    removeListener() {
      // 收到了邀请通知
      this.trtcCalling.off(window.TRTCCalling.EVENT.INVITED, this.handleNewInvitationReceived)
      // 本次通话被取消了
      this.trtcCalling.off(window.TRTCCalling.EVENT.CALLING_CANCEL, this.handleInviterCancel)
      // 本次通话超时未应答
      this.trtcCalling.off(window.TRTCCalling.EVENT.CALLING_TIMEOUT, this.handleCallTimeout)
      // 用户进房
      this.trtcCalling.off(window.TRTCCalling.EVENT.USER_ENTER, this.handleUserEnter)
      // 用户退出房间
      this.trtcCalling.off(window.TRTCCalling.EVENT.USER_LEAVE, this.handleUserLeave)
      // 重复登录，被踢出房间
      this.trtcCalling.off(window.TRTCCalling.EVENT.KICKED_OUT, this.handleKickedOut)
      // 远端用户开启/关闭了摄像头
      this.trtcCalling.off(window.TRTCCalling.EVENT.USER_VIDEO_AVAILABLE, this.handleUserVideoChange)
      // 远端用户开启/关闭了麦克风
      this.trtcCalling.off(window.TRTCCalling.EVENT.USER_AUDIO_AVAILABLE, this.handleUserAudioChange)
      // 本次通话结束
      this.trtcCalling.off(window.TRTCCalling.EVENT.CALLING_END, this.handleCallEnd)
      // 错误回调
      this.trtcCalling.off(window.TRTCCalling.EVENT.ERROR, this.handleError)
    },
    // 收到了邀请通知
    handleNewInvitationReceived(payload) {
      console.log('收到了邀请通知---------------------------')
      const { inviteID, sponsor, inviteData } = payload
      this.inviteData = inviteData
      this.inviteID = inviteID
      this.inviterName = sponsor
      this.inviterUserId = sponsor
      this.show = true
    },
    // 本次通话被取消了
    handleInviterCancel() {
      console.log('本次通话被取消了---------------------------')
      // 邀请被取消
      this.handleHangup(false)
    },
    // 用户进房
    handleUserEnter({ userID }) {
      console.log('用户进房---------------------------', userID)
      try {
        this.trtcCalling.startRemoteView({
          userID: userID,
          videoViewDomID: 'video-big'
        })
        this.trtcCalling.startLocalView({
          userID: this.user.phone,
          videoViewDomID: 'video-small'
        })
        this.$nextTick(() => {
          this.statusName = '接听'
          this.setDuration()
        })
      } catch (e) {
        this.$dialog
          .alert({
            title: '提示',
            message: '获取不到视频资源，请重试'
          })
          .then(() => {
            this.handleHangup(true)
          })
      }
    },
    // 用户退出房间
    handleUserLeave({ userID }) {
      console.log('用户退出房间---------------------------', userID)
      this.statusName = ''
      // this.handleHangup(true)
    },
    // 重复登录，被踢出房间
    handleKickedOut() {
      console.log('重复登录，被踢出房间---------------------------')
      // 重复登陆，被踢出房间
      this.trtcCalling.logout()
      this.show = false
    },
    // 本次通话超时未应答
    handleCallTimeout() {
      console.log('本次通话超时未应答---------------------------')
      this.handleHangup(false)
    },
    // 本次通话结束
    handleCallEnd() {
      console.log('本次通话结束---------------------------')
      this.handleHangup(false)
      Object.keys(localStorage).forEach(function (key) {
        if (/^TIM_|^loglevel/.test(key)) {
          localStorage.removeItem(key)
        }
      })
    },
    // 远端用户开启/关闭了摄像头
    handleUserVideoChange({ userID, isVideoAvailable }) {
      console.log('远端用户开启/关闭了摄像头---------------------------', userID, isVideoAvailable)
    },
    // 远端用户开启/关闭了麦克风
    handleUserAudioChange({ userID, isAudioAvailable }) {
      console.log('远端用户开启/关闭了麦克风---------------------------', userID, isAudioAvailable)
    },
    // 错误回调
    handleError(error) {
      console.log('错误回调---------------------------', error)
    },
    // 拒绝
    async handleRejectCall() {
      if (this.statusName === '接听中') return false
      this.statusName = '拒接'
      try {
        const { callType } = this.inviteData
        await this.trtcCalling.reject({
          inviteID: this.inviteID,
          isBusy: false,
          callType
        })
        this.handleHangup(false)
      } catch (e) {
        this.handleHangup(false)
      }
    },
    // 接收
    handleAccept() {
      if (this.statusName === '接听中') return false
      this.statusName = '接听中'
      this.handleDebounce(this.handleAcceptCall(), 500)
    },
    handleDebounce(func, wait) {
      const context = this
      const args = arguments
      if (timeout) clearTimeout(timeout)
      timeout = setTimeout(() => {
        func.apply(context, args)
      }, wait)
    },
    async handleAcceptCall() {
      try {
        const { callType, roomID } = this.inviteData
        await this.trtcCalling.accept({
          inviteID: this.inviteID,
          roomID,
          callType
        })
      } catch (e) {
        this.handleHangup(false)
      }
    },
    // 挂断
    handleHangup(hangup) {
      hangup && this.trtcCalling.hangup()
      this.show = false
      this.duration = 0
      this.durationFormat = ''
      if (this.timer) {
        clearInterval(this.timer)
        this.timer = null
      }
      setTimeout(() => {
        this.statusName = ''
        this.isAudioAvailable = true
        this.videoChangeFlag = true
        document.getElementById('video-small-warp').style.left = 'auto'
        document.getElementById('video-small-warp').style.right = '32px'
        document.getElementById('video-small-warp').style.top = '28px'
      }, 200)
    },
    // 本地和远程视频切换
    handleVideoClick() {
      this.videoChangeFlag = !this.videoChangeFlag
      if (this.videoChangeFlag) {
        this.trtcCalling.stopRemoteView({
          userID: this.inviterUserId,
          videoViewDomID: 'video-small'
        })
        this.trtcCalling.stopLocalView({
          userID: this.user.phone,
          videoViewDomID: 'video-big'
        })
        // 远程在大框
        this.trtcCalling.startRemoteView({
          userID: this.inviterUserId,
          videoViewDomID: 'video-big'
        })
        this.trtcCalling.startLocalView({
          userID: this.user.phone,
          videoViewDomID: 'video-small'
        })
      } else {
        this.trtcCalling.stopRemoteView({
          userID: this.inviterUserId,
          videoViewDomID: 'video-big'
        })
        this.trtcCalling.stopLocalView({
          userID: this.user.phone,
          videoViewDomID: 'video-small'
        })
        // 远程在小框
        this.trtcCalling.startRemoteView({
          userID: this.inviterUserId,
          videoViewDomID: 'video-small'
        })
        this.trtcCalling.startLocalView({
          userID: this.user.phone,
          videoViewDomID: 'video-big'
        })
      }
    },
    // 计时
    setDuration() {
      if (this.timer) {
        clearInterval(this.timer)
        this.timer = null
      }
      this.duration = 0
      this.durationFormat = formatTimes.formatDuration(this.duration)
      this.timer = setInterval(() => {
        this.duration += 1
        this.durationFormat = formatTimes.formatDuration(this.duration)
      }, 1000)
    }
  },
  beforeDestroy() {
    this.removeListener()
    this.trtcCalling.logout()
  }
}
</script>
<style lang="less" scope>
.trtcCalling-container {
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
}
.trtcCalling-call-title {
  position: absolute;
  top: 40%;
  z-index: 2;
  width: 100%;
  text-align: center;
  line-height: 48px;
  color: #ffffff;
  &-name {
    font-size: 36px;
  }
  &-text {
    font-size: 28px;
    color: rgba(255, 255, 255, 0.6);
  }
}
.trtcCalling-answer-title {
  position: relative;
  z-index: 2;
  width: 100%;
  padding: 24px 42px;
  line-height: 48px;
  color: #ffffff;
  &-name {
    font-size: 36px;
  }
  &-text {
    font-size: 28px;
    color: rgba(255, 255, 255, 0.6);
  }
}
.trtcCalling-video {
  &-big {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1;
  }
  &-small {
    position: absolute;
    top: 28px;
    right: 32px;
    z-index: 2;
    width: 140px;
    height: 216px;
    line-height: 48px;
    &-video {
      width: 100%;
      height: 100%;
      border-radius: 16px;
      overflow: hidden;
    }
    &-text {
      font-size: 24px;
      text-align: center;
      color: #fff;
    }
  }
  &-position {
    top: 28px;
    right: 32px;
  }
}
.trtcCalling-operate {
  position: absolute;
  bottom: 60px;
  z-index: 2;
  width: 100%;
  &-duration {
    margin-bottom: 24px;
    font-size: 36px;
    text-align: center;
    color: #ffffff;
  }
  &-img {
    width: 120px;
  }
  &-text {
    margin-top: 12px;
    color: #ffffff;
    font-size: 28px;
  }
}
</style>
